package iDirection;

import java.awt.BasicStroke;
import java.awt.Button;
import java.awt.Color;
import java.awt.FileDialog;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.MenuItem;
import java.awt.Polygon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;

public class iDirection extends Frame implements ActionListener {
	BufferedImage bufferedImage, bufferedImageBackup;
	Image image;
	Menu menu;
	MenuBar menubar;
	MenuItem menuitem1, menuitem2, menuitem3, menuitem4;
	Button button1, button2, button3, button4, button5;
	FileDialog dialog;

	public static void main(String[] args) {
		new iDirection();
	}

	public iDirection() {
		setSize(400, 360);

		setTitle("iDirection");

		setVisible(true);

		setLayout(null);

		this.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});

		button1 = new Button("Direction");
		button1.setBounds(getWidth() / 2 - 30, getHeight() - 50, 60, 20);
		add(button1);
		button1.addActionListener(this);

		menubar = new MenuBar();

		menu = new Menu("File");

		menuitem1 = new MenuItem("Open...");
		menu.add(menuitem1);
		menuitem1.addActionListener(this);

		menuitem2 = new MenuItem("Save As...");
		menu.add(menuitem2);
		menuitem2.addActionListener(this);

		menuitem3 = new MenuItem("Undo");
		menu.add(menuitem3);
		menuitem3.addActionListener(this);

		menuitem4 = new MenuItem("Exit");
		menu.add(menuitem4);
		menuitem4.addActionListener(this);

		menubar.add(menu);

		setMenuBar(menubar);

		dialog = new FileDialog(this, "File Dialog");
	}

	public void paint(Graphics g) {
		if (bufferedImage != null) {
			g.drawImage(bufferedImage, getSize().width / 2
					- bufferedImage.getWidth() / 2, getInsets().top + 20, this);
		}
	}

	public void drawDirection(BufferedImage bufferedImage) {

		bufferedImageBackup = bufferedImage;

		Graphics2D gp = bufferedImage.createGraphics();
		gp.setColor(Color.red);
		gp.setStroke(new BasicStroke(3));
		gp.drawLine(0, 0, 50, 50);
		drawArrow(gp, 0, 0, 50, 50);
	}

	public void drawArrow(Graphics2D g2, int x1, int y1, int x2, int y2) {

		g2.drawPolygon(getArrow(x1, y1, x2, y2, 9, 0, 0.5)); // startx,starty,endx,endy,headsize,difference,factor

		g2.fillPolygon(getArrow(x1, y1, x2, y2, 9, 0, 0.5));
	}

	public Polygon getArrow(int x1, int y1, int x2, int y2, int headsize,
			int difference, double factor) {

		int[] crosslinebase = getArrowHeadLine(x1, y1, x2, y2, headsize);

		int[] headbase = getArrowHeadLine(x1, y1, x2, y2, headsize - difference);

		int[] crossline = getArrowHeadCrossLine(crosslinebase[0],
				crosslinebase[1], x2, y2, factor);

		Polygon head = new Polygon();

		head.addPoint(headbase[0], headbase[1]);

		head.addPoint(crossline[0], crossline[1]);

		head.addPoint(x2, y2);

		head.addPoint(crossline[2], crossline[3]);

		head.addPoint(headbase[0], headbase[1]);

		head.addPoint(x1, y1);

		return head;
	}

	public int[] getArrowHeadLine(int xsource, int ysource, int xdest,
			int ydest, int distance) {
		int[] arrowhead = new int[2];

		int headsize = distance;

		double stretchfactor = 0;

		stretchfactor = 1 - (headsize / (Math
				.sqrt(((xdest - xsource) * (xdest - xsource))
						+ ((ydest - ysource) * (ydest - ysource)))));

		arrowhead[0] = (int) (stretchfactor * (xdest - xsource)) + xsource;

		arrowhead[1] = (int) (stretchfactor * (ydest - ysource)) + ysource;

		return arrowhead;
	}

	public int[] getArrowHeadCrossLine(int x1, int x2, int b1, int b2,
			double factor) {
		int[] crossline = new int[4];

		int xdest = (int) (((b1 - x1) * factor) + x1);

		int ydest = (int) (((b2 - x2) * factor) + x2);

		crossline[0] = (int) ((x1 + x2 - ydest));

		crossline[1] = (int) ((x2 + xdest - x1));

		crossline[2] = crossline[0] + (x1 - crossline[0]) * 2;

		crossline[3] = crossline[1] + (x2 - crossline[1]) * 2;

		return crossline;

	}

	public void actionPerformed(ActionEvent event) {

		if (event.getSource() == menuitem1) {

			dialog.setMode(FileDialog.LOAD);

			dialog.setVisible(true);

			try {
				if (!dialog.getFile().equals("")) {
					File input = new File(dialog.getDirectory()
							+ dialog.getFile());
					System.out.println(dialog.getDirectory() + dialog.getFile()); 
					bufferedImage = ImageIO.read(input);

					setSize(getInsets().left + getInsets().right
							+ Math.max(400, bufferedImage.getWidth() + 60),
							getInsets().top
									+ getInsets().bottom
									+ Math.max(340,
											bufferedImage.getHeight() + 60));

					button1.setBounds(getWidth() / 2 - 30, getHeight() - 30,
							60, 20);
				}
			} catch (Exception e) {
				System.out.println(e.getMessage());
			}

			repaint();
		}

		if (event.getSource() == menuitem2) {

			dialog.setMode(FileDialog.SAVE);

			dialog.setVisible(true);

			try {
				if (!dialog.getFile().equals("")) {

					String outfile = dialog.getFile();

					File outputFile = new File(dialog.getDirectory() + outfile);

					ImageIO.write(bufferedImage, outfile.substring(outfile
							.length() - 3, outfile.length()), outputFile);
				}
			} catch (Exception e) {
				System.out.println(e.getMessage());
			}
		}

		if (event.getSource() == button1) {

			drawDirection(bufferedImage);

			repaint();
		}

	}
}
